home *** CD-ROM | disk | FTP | other *** search
- /*======================================================================
- I N E T R A Y . C
- doc: Mon Feb 24 16:20:04 1992
- dlm: Tue Aug 17 13:51:54 1993
- (c) 1992 ant@julia
- uE-Info: 414 31 T 0 0 72 10 2 8 ofnI
- ======================================================================*/
-
- /*#define PRINTSCHEDULE /* print scheduling info */
- /*#define VERBOSE /* print retrys */
-
- #include <stdio.h> /* here we go! */
- #include <signal.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <string.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <sys/time.h>
- #include <sys/param.h>
- #include <rpc/rpc.h>
- #include "inetray.h"
- #include "config.h"
- #include "common.h"
- #include "comm.h"
- #include "rayshade.h"
- #include "options.h"
- #include "picture.h"
- #include "viewing.h"
- #include "rcfile.h"
- #include "lbuffer.h"
- #include "version.h"
- #include "patchlevel.h"
-
- static Pixel **line; /* array for picture data */
- static int bSize; /* blocksize to trace in one sweep */
- static int lSize; /* size of last block in frame */
- static int bNum; /* number of blocks in frame */
- static char *completed; /* array for completed blocks */
- static int doNext = 0; /* next block to trace */
- static int doNBlk = 2; /* number of blocks to send */
- static char pass2 = FALSE; /* 2nd pass through picture */
- static int reDo = 0; /* reDo # of outstanding blocks */
- static int nCompleted = 0; /* number of lines completed per frame */
- static int bCompleted = 0; /* number of blocks completed per frame */
- static int nSvc; /* number of registered servers */
- static int nextB2W; /* next block to write to pic file */
- static int bufPipe[2]; /* 2nd pipe to lBuffer */
- static int tty; /* read from keyboard */
-
- int key; /* session key (exported) */
-
- extern int errno; /* error number to restart syscalls */
-
- main(ac,av)
- int ac; char *av[];
- {
- static void initSelf(),initSubDiv(),initFrame();
- static void printStats(),distAll(),sigCaught(),writeBlocks();
- static int initServers();
- int fd;
- char buf[64];
-
- if ((tty = open("/dev/tty",O_RDONLY)) < 0) { /* keyboard */
- perror("open(/dev/tty)");
- exit(1);
- }
-
- fprintf(stderr,"%s [%s%d]\n",av[0],VERSION,PATCHLEVEL);
- initSelf(ac,av); /* initialize self */
- PictureStart(av); /* open picture file */
-
- key = (int)time(NULL); /* session key */
- fprintf(stderr,"Session Key = %d\n",key);
- rename(KEYFILE,OLDKEYFILE); /* save keyfile */
- fd = open(KEYFILE,O_CREAT|O_WRONLY,0600);
- if (fd < 0) {
- perror("open(KEYFILE)");
- } else {
- sprintf(buf,"%ld\n",key); /* in ASCII */
- if (write(fd,buf,strlen(buf)) < 0) {
- perror("write");
- exit(1);
- }
- close(fd);
- }
-
- initServers(ac,av); /* set up all servers */
- initSubDiv(); /* init frame subdivision */
-
- for (Options.framenum=Options.startframe;
- Options.framenum<=Options.endframe;
- Options.framenum++) {
- initFrame(Options.framenum); /* init & send first requests */
- if (Options.framenum>Options.startframe)
- PictureStart(av); /* write picture in parallel */
- distAll(); /* distribute remaining lines */
- writeBlocks(TRUE); /* write remaining blocks */
- fprintf(stderr,"Cleaning up... [kill");
- killAll(); /* kill running workers */
- fprintf(stderr,", flush");
- flushAll(); /* discard pending input */
- fprintf(stderr,", wait");
- waitAll(); /* wait for workers to come down */
- fprintf(stderr,"]");
- PictureFrameEnd(); /* end picture frame */
- }
- PictureEnd();
- Options.framenum = Options.endframe; /* fix for stats */
- printStats();
- fprintf(stderr,"Exiting... [terminate");
- terminateAll(); /* now exit everything */
- fprintf(stderr,", close");
- closeAll();
- fprintf(stderr,"]\n");
- exit(0);
- }
-
- /*----------------------------------------------------------------------*/
- /* initSelf and supporting routines */
- /*----------------------------------------------------------------------*/
-
- static void busError() /* SUN4 weird bus errors */
- {
- fprintf(stderr,"Warning: SIGBUS caught!\n");
- }
-
- static void defSignals() /* install default sigs */
- {
- void sigCaught();
-
- signal(SIGHUP,sigCaught); /* all sigs which could mean */
- signal(SIGINT,sigCaught); /* terminate */
- signal(SIGQUIT,sigCaught);
- signal(SIGABRT,sigCaught);
- signal(SIGTERM,sigCaught);
- signal(SIGTSTP,sigCaught);
- signal(SIGUSR1,sigCaught);
- signal(SIGUSR2,sigCaught);
- signal(SIGBUS,busError); /* sometimes on SUN4s */
- signal(SIGPIPE,shutDown); /* ^C in pipeline */
- }
-
- static void sigCaught() /* abort signal rcved */
- {
- char ans;
-
- fprintf(stderr,"\nSignal received...\n");
- if (getppid() != 1) { /* parent alive */
- fprintf(stderr,"Really abort <y/n>?");
- do { /* get ans from keyboard */
- if (read(tty,&ans,1) != 1) {
- perror("read(tty)");
- exit(1);
- }
- }
- while ((ans != 'y') && (ans != 'Y') &&
- (ans != 'n') && (ans != 'N'));
- if ((ans == 'y') || (ans == 'Y')) shutDown(0);
- } else shutDown(0);
- defSignals();
- }
-
-
- static void initFrame(f) /* init frame */
- int f;
- {
- int i;
- void dist1st();
-
- for (i=0; i<bNum; i++) /* clear completed flags */
- completed[i] = FALSE;
- doNext = nCompleted = 0; /* reset counters */
- pass2 = FALSE;
- reDo = nextB2W = bCompleted = 0;
- fprintf(stderr,"\nFrame #%d:\n",f);
- dist1st(f); /* begin trace */
- }
-
- static void initSelf(ac,av) /* init stuff */
- int ac; char *av[];
- {
- int bPid,i,lnSize,saveIn,p[2];
-
- readRc(); /* read .rc-file */
-
- if (pipe(p) < 0) { /* set up input */
- perror("pipe");
- exit(1);
- }
-
- if (pipe(bufPipe) < 0) { /* 2nd lBuffer pipe */
- perror("pipe");
- exit(1);
- }
- bPid = lPreBuffer(p,bufPipe);
-
- saveIn = dup(IN); /* redirect stdin */
- close(IN);
- dup(p[IN]);
- close(p[IN]);
-
- RSInitialize(ac,av); /* options, file, ... */
- kill(bPid,SIGUSR1); /* kill if still killable */
-
- close(IN); /* reset stdin */
- dup(saveIn);
-
- wait(NULL); /* from popen() */
- defSignals(); /* signals */
-
- line = (Pixel **)malloc(Screen.ysize * sizeof(Pixel *));
- if (line == NULL) {
- fprintf(stderr,"malloc() failed\n");
- exit(1);
- }
- lnSize = Screen.xsize * sizeof(Pixel);
- for (i=0; i<Screen.ysize; i++) {
- line[i] = (Pixel *)malloc(lnSize);
- if (line[i] == NULL) {
- perror("malloc");
- exit(1);
- }
- }
- }
-
- static void initSubDiv() /* init frame subdivision */
- {
- bSize = Screen.ysize / nSvc
- / blocksPerServer; /* estimated size of blocks */
- if (bSize < minBlockSize) /* assert bounds */
- bSize = minBlockSize;
- if (bSize > maxBlockSize)
- bSize = maxBlockSize;
- bNum = Screen.ysize / bSize + 1; /* number of blocks */
- lSize = Screen.ysize-(bNum-1)*bSize; /* remaining lines */
- if (lSize == 0) { /* no remaining lines */
- bNum--;
- lSize = bSize;
- }
-
- completed = (char *)malloc(bNum); /* supporting structures */
- if (completed == NULL) {
- fprintf(stderr,"malloc() failed\n");
- exit(1);
- }
- fprintf(stderr,"Frame Subdivision:");
- fprintf(stderr,"\n\t%d Blocks per Frame",bNum);
- fprintf(stderr,"\n\t%d Lines per Block",bSize);
- if (lSize != bSize)
- fprintf(stderr,"\n\t%d Lines in Last Block",lSize);
- }
-
-
- /*----------------------------------------------------------------------*/
- /* distribution */
- /*----------------------------------------------------------------------*/
-
- static int findNext() /* next blockNr */
- {
- int i,sm= -1,nx= -1,next;
-
- for (i=0; i<bNum; i++)
- if (!completed[i]) {
- if (sm < 0) sm = i;
- if ((nx < 0) && (i >= doNext)) nx = i;
- }
- if (sm < 0) return FALSE;
-
- if (nx < 0) { /* original next */
- if (!pass2) {
- fprintf(stderr,"\tEnd of Pass #1\n");
- pass2 = TRUE;
- }
- next = sm;
- } else next = nx;
-
- if (reDo > 0) { /* rescheduled */
- reDo--;
- doNext = sm;
- doNBlk = 1;
- } else if (pass2 || next == bNum-1 || next == bNum-2) {
- doNext = next;
- doNBlk = 1;
- } else {
- doNext = next;
- doNBlk = 2;
- }
- return TRUE;
- }
-
- static void dist1st(frame) /* dist 1 block p. server */
- int frame;
- {
- hInfo *host;
- int res,rpcerr,nTrys;
- sfPrm paramSF;
-
- for (host = hosts; host != NULL; host = host->next) {
- if (!findNext()) return;
- host->fDone = 0;
- if (host->broken) continue;
- paramSF.key = key;
- paramSF.fNr = frame;
- for (nTrys = 10; nTrys > 0; nTrys--) {
- rpcerr = clnt_call(host->clnt,STARTFRAME,
- xdr_sfPrm,¶mSF,
- xdr_int,&res,callTOut);
- if (rpcerr == RPC_SUCCESS) break;
- if (rpcerr == RPC_TIMEDOUT) {
- #ifdef VERBOSE
- fprintf(stderr,"STARTFRAME retry to %s\n",host->name);
- #endif
- host->reTrys++;
- if (nTrys > 1) continue;
- }
- fprintf(stderr,"startframe(): ");
- abort1(host);
- }
- host->request.key = key;
- host->request.bNr = doNext;
- host->request.bSz = (doNext == bNum-1) ? lSize : bSize;
- host->request.lNr = doNext*bSize;
- host->request.nBlocks = doNBlk;
- clnt_call(host->clnt,TRACEBLOCK,
- xdr_tbPrm,&(host->request),
- xdr_void,NULL,now);
- #ifdef PRINTSCHEDULE
- fprintf(stderr,"\tBlock(s) #%d-#%d sent to %s(%d)\n",
- doNext,doNext+doNBlk-1,host->name,host->wid);
- #endif
- doNext += doNBlk;
- }
- }
-
- static void printStats() /* print statistics */
- {
- hInfo *host,*bHost;
- int tot,all,best;
- char nBuf[MAXHOSTNAMELEN+10];
-
- if (getppid() == 1) shutDown(0);
- signal(SIGINT,sigCaught);
- fprintf(stderr,"\nStatistics:\n");
- tot = (Options.framenum-Options.startframe)*Screen.ysize+nCompleted;
- if (tot == 0) tot = 1;
- for (all=0; all<nSvc; all++) {
- best = 0;
- for (host = hosts; host != NULL; host = host->next)
- if (host->done >= best) {
- best = host->done;
- bHost = host;
- }
- if (bHost->done == 0) bHost->done = -1;
- else bHost->done = -bHost->done;
- putc('\t',stderr);
- sprintf(nBuf,"%s[%d]",bHost->name,bHost->pid);
- fprintf(stderr,"\t%-15.14s",nBuf);
- if (bHost->broken) fprintf(stderr,"# ");
- else fprintf(stderr," ");
- if (bHost->reTrys != 0)
- fprintf(stderr,"%4d",bHost->reTrys);
- fprintf(stderr,"\t");
- fprintf(stderr,"%d \t(%d%%)\n",best,100*best/tot);
- }
- for (host = hosts; host != NULL; host = host->next)
- if (host->done == -1) host->done = 0;
- else host->done = -host->done;
- if (getppid() == 1) shutDown(0);
- }
-
- static void writeBlocks(flush)
- char flush;
- {
- int i,bSz,writ = 0; /* write to file */
- hInfo *h;
- fd_set sockSet;
-
- while ((nextB2W < bNum) && completed[nextB2W]) {
- if (writ == 0)
- fprintf(stderr,"\tWriting... ");
- bSz = (nextB2W == bNum-1) ? lSize : bSize;
- for (i=0; i<bSz; i++)
- PictureWriteLine(line[nextB2W*bSize+i]);
- nextB2W++; writ++;
- if (!flush) { /* check for input */
- FD_ZERO(&sockSet);
- for (h = hosts; h != NULL; h = h->next)
- if (!h->broken)
- FD_SET(h->sock,&sockSet);
- if (select(sfdmax+1,&sockSet,
- (fd_set *)NULL,(fd_set *)NULL,
- &now) != 0) {
- fprintf(stderr,"[interrupted] ");
- break;
- }
- }
- }
- if (writ == 1) /* report it */
- fprintf(stderr,"(1 block)\n");
- else if (writ > 1)
- fprintf(stderr,"(%d blocks)\n",writ);
- }
-
- static char getBlock(host) /* get traced block */
- hInfo *host;
- {
- pixArr xdrline;
- int bNr,bSz,i; /* block info */
- XDR *xdrs;
- hInfo *h;
-
- xdrs = &(host->xdrs);
- if (!xdrrec_skiprecord(xdrs)) { /* read next record*/
- fprintf(stderr,"xdrrec_skiprecord(): ");
- abort1(host);
- return FALSE;
- }
- if (!xdr_int(xdrs,&bNr)) { /* get block number */
- abort1(host);
- return FALSE;
- }
-
- bSz = (bNr == bNum-1) ? lSize : bSize; /* calc block size */
-
- for (i=0; i<bSz; i++) { /* read all lines */
- xdrline.pixArr_val = (xdrPix *)line[bNr*bSize+i];
- if (!xdr_pixArr(xdrs,&xdrline)) {
- fprintf(stderr,"xdr_pixArr(): ");
- abort1(host);
- return FALSE;
- }
- }
- host->request.nBlocks--;
- #ifdef PRINTSCHEDULE
- fprintf(stderr,"\tBlock #%d received from %s(%d)\n",
- bNr,host->name,host->wid);
- fprintf(stderr,"\t%d Block(s) remaining\n",
- host->request.nBlocks);
- #endif
- if (!completed[bNr]) { /* reporting & statistics */
- completed[bNr] = TRUE;
- if (nCompleted/Options.report_freq <
- (nCompleted+bSz)/Options.report_freq) {
- fprintf(stderr,"\tFinished line %d\n",nCompleted+bSz);
- }
- nCompleted += bSz; /* update stats */
- bCompleted++;
- host->done += bSz;
- host->fDone += bSz;
- /* if (bCompleted == bNum/2) {
- for (h = hosts; h != NULL; h = h->next)
- if (h->fDone == 0) reDo++;
- if (reDo > bNum/4) reDo = 0;
- reDo *= 2;
- if (reDo == 1)
- fprintf(stderr,"\t1 block rescheduled\n");
- else
- fprintf(stderr,"\t%d blocks rescheduled\n",reDo);
- } */
- }
- writeBlocks(FALSE);
- return TRUE;
- }
-
-
- static void distAll() /* block distribution routine */
- {
- fd_set sockSet;
- int res;
- hInfo *host;
- char timedOut;
-
- do { /* loop on all blocks */
- signal(SIGINT,printStats);
-
- restartSelect:
- FD_ZERO(&sockSet); /* select() on sockets */
- for (host = hosts; host != NULL; host = host->next)
- if (!host->broken)
- FD_SET(host->sock,&sockSet);
- timedOut = TRUE;
- res = select(sfdmax+1,&sockSet,
- (fd_set *)NULL,(fd_set *)NULL,
- &resend);
- if (res < 0) {
- if (errno == EINTR) goto restartSelect;
- perror("select");
- exit(1);
- }
-
- for (host = hosts; host != NULL; host = host->next) {
- if (!FD_ISSET(host->sock,&sockSet)) continue;
- if (host->broken) continue;
- timedOut = FALSE;
- if (!getBlock(host)) /* read one result */
- continue; /* connection broken */
- if (host->request.nBlocks > 0) /* not done yet */
- continue;
- if (!findNext()) return; /* next line to trace */
- host->request.key = key; /* next block */
- host->request.bNr = doNext;
- host->request.bSz = (doNext == bNum-1) ? lSize : bSize;
- host->request.lNr = doNext * bSize;
- host->request.nBlocks = doNBlk;
- (void)clnt_call(host->clnt,TRACEBLOCK,
- xdr_tbPrm,&(host->request),
- xdr_void,NULL,
- now);
- #ifdef PRINTSCHEDULE
- fprintf(stderr,"\tBlock(s) #%d-#%d sent to %s(%d)\n",
- doNext,doNext+doNBlk-1,host->name,host->wid);
- #endif
- doNext += doNBlk;
- }
-
- } FOREVER;
- }
-
- /*----------------------------------------------------------------------*/
- /* initClients() */
- /*----------------------------------------------------------------------*/
-
- static char *makePStr(ac,av) /* build param-str */
- int ac; char *av[];
- {
- int abp,ap,i;
- static char argbuf[256];
-
- for (abp=0,ap=0; ap < ac; ap++) {
- argbuf[abp++] = '\'';
- for (i=0; av[ap][i] != '\0'; i++)
- argbuf[abp++] = av[ap][i];
- argbuf[abp++] = '\'';
- argbuf[abp++] = ' ';
- }
- argbuf[abp] = '\0';
- return argbuf;
- }
-
- static int initServers(ac,av) /* init all servers */
- int ac; char *av[];
- {
- char cwd[MAXPATHLEN],hname[MAXHOSTNAMELEN];
- char *getcwd();
- struct stat sBuf;
-
- if (gethostname(hname,MAXHOSTNAMELEN) < 0) {
- perror("gethostname");
- exit(1);
- }
- if (fstat(bufPipe[IN],&sBuf) < 0) { /* buffer alive? */
- perror("fstat");
- exit(1);
- }
- fprintf(stderr,"Registering... [");
- registerSvc(hname,makePStr(ac,av),
- getcwd(cwd,MAXPATHLEN),sBuf.st_size>0);
- nSvc = nRunning;
- if (nSvc == 0) {
- fprintf(stderr,"\nError: no Inetray Servers answering!\n");
- exit(1);
- }
- fprintf(stderr,"\n[%d workers registered]\n",nSvc);
-
- if (sBuf.st_size>0) { /* send file */
- fprintf(stderr,"Distibuting StdIn...");
- distribute(bufPipe[IN]);
- fprintf(stderr,"\n");
- }
- wait(NULL); /* wait for buffer */
- }
-